package search

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
)

// CsdnResult 与 TypeScript 定义一致的搜索结果结构体
type CsdnResult struct {
	Title       string `json:"title"`
	URL         string `json:"url"`
	Description string `json:"description"`
	Source      string `json:"source"`
	Engine      string `json:"engine"`
}

// csdnSearchResponse CSDN 搜索接口响应结构体（仅解析需要的字段）
type csdnSearchResponse struct {
	ResultVos []struct {
		Digest      string `json:"digest"`       // 摘要
		Title       string `json:"title"`        // 标题
		UrlLocation string `json:"url_location"` // 文章链接
		Nickname    string `json:"nickname"`     // 作者（来源）
	} `json:"result_vos"` // 搜索结果数组
}

// SearchCsdn CSDN 搜索函数，参数为查询词和结果数量限制
func SearchCsdn(query string, limit int) ([]CsdnResult, error) {
	var allResults []CsdnResult
	pn := 1 // 分页页码，从1开始

	for len(allResults) < limit {
		// 构建查询参数
		params := url.Values{}
		params.Add("q", query)
		params.Add("p", fmt.Sprintf("%d", pn))

		// 创建请求
		reqURL := "https://so.csdn.net/api/v3/search?" + params.Encode()
		req, err := http.NewRequest("GET", reqURL, nil)
		if err != nil {
			return nil, fmt.Errorf("创建请求失败: %w", err)
		}

		// 设置请求头（与原 TS 代码一致）
		req.Header.Set("Pragma", "no-cache")
		req.Header.Set("Cookie", "uuid_tt_dd=10_20283040220-1750745713898-623562; dc_session_id=10_1750745713898.508399; dc_sid=0aa6fae5250c4389fac68320b1cb43b2; waf_captcha_marker=1b4e9099857d7aedf0941f03fa70bfb22ea2153f7fa053b8101ed28dc1504b11; c_pref=default; c_ref=default; fid=20_93458541565-1750745714849-027048; c_first_ref=default; c_first_page=https%3A//so.csdn.net/so/search%3Fq%3Dweb%2520search%2520mcp; c_dsid=11_1750745714849.980720; c_segment=10; c_page_id=default; creative_btn_mp=1; log_Id_view=9; fe_request_id=1750745715289_2973_2073791; dc_tos=syck1f; log_Id_pv=1; log_Id_click=1; uuid_tt_dd=10_20283045860-1751096847125-425142; dc_session_id=10_1751096847125.891975")
		req.Header.Set("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
		req.Header.Set("Accept", "*/*")
		req.Header.Set("Host", "so.csdn.net")
		req.Header.Set("Connection", "keep-alive")

		// 发送请求（15秒超时）
		client := &http.Client{Timeout: 15 * time.Second}
		resp, err := client.Do(req)
		if err != nil {
			return nil, fmt.Errorf("发送请求失败: %w", err)
		}
		defer resp.Body.Close()

		// 检查响应状态
		if resp.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("请求失败，状态码: %d", resp.StatusCode)
		}

		// 解析 JSON 响应
		var csdnResp csdnSearchResponse
		decoder := json.NewDecoder(resp.Body)
		if err := decoder.Decode(&csdnResp); err != nil {
			return nil, fmt.Errorf("解析响应失败: %w", err)
		}

		// 检查结果数组是否有效
		if csdnResp.ResultVos == nil || len(csdnResp.ResultVos) == 0 {
			fmt.Println("⚠️ No more results, ending early....")
			break
		}

		// 转换为 CsdnResult 格式
		var pageResults []CsdnResult
		for _, re := range csdnResp.ResultVos {
			pageResults = append(pageResults, CsdnResult{
				Title:       re.Title,
				URL:         re.UrlLocation,
				Description: re.Digest,
				Source:      re.Nickname,
				Engine:      "csdn",
			})
		}

		// 合并结果
		allResults = append(allResults, pageResults...)

		// 准备下一页
		pn += 1
	}

	// 截取到指定数量的结果
	if len(allResults) > limit {
		allResults = allResults[:limit]
	}

	return allResults, nil
}

// FetchCsdnArticle 抓取 CSDN 文章内容，返回文章纯文本
func FetchCsdnArticle(url string) (map[string]string, error) {
	// 创建请求
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %w", err)
	}

	// 设置请求头（与原 TS 代码一致）
	req.Header.Set("Accept", "*/*")
	req.Header.Set("Host", "blog.csdn.net")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Cookie", "https_waf_cookie=771a8075-77ae-4b2cdf3bda08cd28ad372861867be773d8c1; uuid_tt_dd=10_20283045860-1751096847125-425142; dc_session_id=10_1751096847125.891975; waf_captcha_marker=318c5c7f316f665febdb746a58e039a681a94708df7a26376ed47720663cd99d")
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")

	// 发送请求（15秒超时）
	client := &http.Client{Timeout: 15 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("发送请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("请求失败，状态码: %d", resp.StatusCode)
	}

	// 解析 HTML，提取文章内容（对应 #content_views 元素）
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("解析HTML失败: %w", err)
	}

	// 获取文章纯文本内容，清理空格
	content := strings.TrimSpace(doc.Find("#content_views").Text())

	// 按原 TS 格式返回结果（map 对应 { content: string }）
	return map[string]string{
		"content": content,
	}, nil
}
